package biscuit;

import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.transport.THttpClient;

import com.evernote.edam.type.User;
import com.evernote.edam.userstore.UserStore;
import com.evernote.oauth.consumer.SimpleOAuthRequest;

@WebServlet(urlPatterns = "/" + AuthServlet.SERVLET_URL_BASE)
public class AuthServlet extends HttpServlet {

	private static final long serialVersionUID = -4099191990249828904L;

	public static final String SERVLET_URL_BASE = "authServlet";
	private static final String REQUEST_URL_BASE = "https://www.evernote.com";

	static final String consumerKey = "prosopher-8329";
	static final String consumerSecret = "e24b41032b1921a6";

	static final String requestTokenUrl = REQUEST_URL_BASE + "/oauth";
	static final String accessTokenUrl = REQUEST_URL_BASE + "/oauth";
	static final String authorizationUrlBase = REQUEST_URL_BASE + "/OAuth.action";
	static final String noteStoreUrlBase = REQUEST_URL_BASE + "/edam/note/";

	static final String callbackUrl = SERVLET_URL_BASE + "?action=callbackReturn";
	
	private String requestToken;
	private String verifier;
	private String accessToken;
	private String shardId;

	@Override
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		// 세션 및 매개변수 값 추출
		HttpSession session = request.getSession();
		
		requestToken = (String) session.getAttribute("requestToken");
		verifier = (String) session.getAttribute("verifier");
		accessToken = (String) session.getAttribute("accessToken");
		shardId = (String) session.getAttribute("shardId");

		String action = request.getParameter("action");

		// 출력 Content 타입 세팅
		response.setContentType("text/html");
		response.setCharacterEncoding("UTF-8");

		// OAuth 인증 처리 부분
		if (action != null) {
			
			try {
				if ("getRequestToken".equals(action)) {
					
					// 1단계
					// 새로운 requestToken 을 받아온다.
					SimpleOAuthRequest oauthRequestor = new SimpleOAuthRequest(
							requestTokenUrl, consumerKey, consumerSecret,
							null);

					// Set the callback URL
					String thisUrl = request.getRequestURL().toString();
					String cbUrl = thisUrl.substring(0, thisUrl.lastIndexOf('/') + 1) + callbackUrl;
					oauthRequestor.setParameter("oauth_callback", cbUrl);

					Map<String, String> reply = oauthRequestor.sendRequest();
					requestToken = reply.get("oauth_token");
					session.setAttribute("requestToken", requestToken);

					// 2단계
					String authorizationUrl = authorizationUrlBase + "?oauth_token=" + requestToken;
					response.sendRedirect(response.encodeRedirectURL(authorizationUrl));

				} else if ("callbackReturn".equals(action)) {
					
					requestToken = request.getParameter("oauth_token");
					verifier = request.getParameter("oauth_verifier");
					session.setAttribute("verifier", verifier);

					// 3단계
					response.sendRedirect(response.encodeRedirectURL(SERVLET_URL_BASE + "?action=getAccessToken"));
					
				} else if ("getAccessToken".equals(action)) {

					// Send an OAuth message to the Provider asking to
					// exchange the
					// existing Request Token for an Access Token
					SimpleOAuthRequest oauthRequestor = new SimpleOAuthRequest(
							requestTokenUrl, consumerKey, consumerSecret, null);
					oauthRequestor.setParameter("oauth_token",
							(String) session.getAttribute("requestToken"));
					oauthRequestor.setParameter("oauth_verifier",
							(String) session.getAttribute("verifier"));

					// TODO
					// 로그인 취소 눌렀을 경우 에러 나는 부분 처리
					Map<String, String> reply = oauthRequestor.sendRequest();

					accessToken = reply.get("oauth_token");
					shardId = reply.get("edam_shard");
					session.setAttribute("accessToken", accessToken);
					session.setAttribute("shardId", shardId);

					// 사용자 이름을 추출해서 세션에 저장해 둔다.
					String userAgent = "Biscuit Project";
					String userStoreUrl = "https://www.evernote.com/edam/user";
					THttpClient userStoreTrans = new THttpClient(userStoreUrl);
					userStoreTrans.setCustomHeader("User-Agent", userAgent);
					TBinaryProtocol userStoreProt = new TBinaryProtocol(userStoreTrans);
					UserStore.Client userStore = new UserStore.Client(userStoreProt, userStoreProt);
					
					User user = userStore.getUser(accessToken);
					
					session.setAttribute("userId", user.getUsername());
					
					// 4단계
					// 다 끝났으므로 주소를 초기화한다.
					response.sendRedirect(response.encodeRedirectURL("list.html"));
					
				} else if ("logout".equals(action)) {

					// 모든 세션 정보를 삭제한다.
					for (Enumeration<?> names = session.getAttributeNames(); names.hasMoreElements();) {
						session.removeAttribute((String) names .nextElement());
					}
					
					accessToken = null;
					requestToken = null;
					verifier = null;

					// 다 끝났으므로 주소를 초기화한다.
					response.sendRedirect(response.encodeRedirectURL("index.html"));
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
	}
}
